Skip to content

fix(preview): regenerate previews whose stored file is gone - #63486

Open
rayvincent2 wants to merge 1 commit into
nextcloud:masterfrom
rayvincent2:fix/63349/regenerate-missing-preview-files
Open

fix(preview): regenerate previews whose stored file is gone#63486
rayvincent2 wants to merge 1 commit into
nextcloud:masterfrom
rayvincent2:fix/63349/regenerate-missing-preview-files

Conversation

@rayvincent2

@rayvincent2 rayvincent2 commented Aug 22, 2026

Copy link
Copy Markdown

Summary

If a preview database row exists but the stored file is gone, generation used that row and then failed when it tried to read the file. Generator now checks that the file is still present, deletes the stale row if it is not, and regenerates the preview. That covers a missing max preview and missing extra sizes when several sizes are configured for one file.

Unit tests cover local storage, object storage, and multiple sizes per file.

Live test: I applied this change on a Nextcloud 34.0.3 instance with local preview storage. occ preview:generate had been failing with NotFoundException from LocalPreviewStorage::readPreview (DB row for 1535-2048-max.jpg, file missing). After the change the same command succeeded. Several other images were in the same state. Opening them in Memories requested previews again and those thumbnails regenerated instead of staying broken.

I have not live-tested object store or a full preview:generate-all re-run.

Checklist

AI (if applicable)

  • The content of this PR was partly or fully generated using AI

I used Grok to implement the fix and tests; I reviewed the diff, ran the unit tests, and verified it on 34.0.3.

@rayvincent2
rayvincent2 requested a review from a team as a code owner August 22, 2026 07:09
@rayvincent2
rayvincent2 requested review from Altahrim, come-nc, icewind1991 and salmart-dev and removed request for a team August 22, 2026 07:09
When a preview row exists in the database but the backing file is
missing, preview:generate failed with NotFoundException from
LocalPreviewStorage::readPreview. Drop the stale row and generate a
new preview instead so occ preview:generate and preview:generate-all
can repair as they run.

Fixes: nextcloud#63349

Assisted-by: Grok:grok-4.6
Signed-off-by: Ray Vincent <rayhvincent@gmail.com>
@rayvincent2
rayvincent2 force-pushed the fix/63349/regenerate-missing-preview-files branch from f4090ea to 2e23e9c Compare August 22, 2026 07:12
@rayvincent2

rayvincent2 commented Aug 23, 2026

Copy link
Copy Markdown
Author

Follow-up to the live-test note in the description: I have now run a path-scoped preview:generate-all on production (34.0.3 + this patch, local preview storage).

Context: I had already completed successful preview:generate-all runs over all images earlier (including repairs of missing preview files via this change). The runs below are not a cold full regenerate of missing previews — they are re-runs over a tree where previews already exist. “Cold” vs “warm” here only means first pass vs second/third pass with OS page/dentry cache for stat (and similar) warmed.

docker exec -u www-data -e PHP_MEMORY_LIMIT=2G nextcloud-manual_install-nextcloud \
  php -d memory_limit=2G /var/www/html/occ preview:generate-all -vv \
  --path "/ray/files/Photos/My Photos/2026"

Results for /ray/files/Photos/My Photos/2026:

  • 1050 source files (find ray/files/Photos/My\ Photos/2026: -type f | wc -l)
  • Verbose log showed 1050 Generating previews for each run
  • First pass (cold) finished in ~17s (real 0m17.622s)
  • Second pass (warm) finished in ~3s (real 0m3.097s)
  • Third pass (warm) finished in ~3s (real 0m3.194s)

So this is a smoke / regression check that preview:generate-all still walks the tree cleanly with the patch applied when previews are already present. The original bug (DB row present, preview file missing → hard fail on readPreview) was verified earlier with single-file preview:generate on known-broken rows.

I still have not live-tested object-store primary storage.

'store' => $store,
] = $this->getObjectStoreInfoForExistingPreview($preview);

return $store->objectExists($urn);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this generates network requests, which is not great for performance. I wonder if for object store we could just always return true (at least for now until a better solution is found)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Preview generation fails when DB entry exists, but local file does not

3 participants